/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package calendarioservice;

import calendarioentities.Calendario;
import calendarioentities.Cita;
import calendarioentities.Persona;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;

/**
 *
 * @author alyer
 */
@Stateless
@Path("persona")
public class PersonaFacadeREST extends AbstractFacade<Persona> {
    @PersistenceContext(unitName = "calendarioRESTFULPU")
    private EntityManager em;
    @Context
    private UriInfo context;

    public PersonaFacadeREST() {
        super(Persona.class);
    }

    @POST
    @Override
    @Consumes({"application/xml", "application/json"})
    public void create(Persona entity) {
        super.create(entity);
    }

    @PUT
    @Consumes({"application/xml", "application/json"})
    public Response edit(Persona entity) {
        super.edit(entity);
        URI createduri = null;
        try {        
          createduri = new URI(context.getAbsolutePath().toString()+"/"+entity.getIdpersona());
        } catch (URISyntaxException ex) { }
        return Response.status(Status.NO_CONTENT).header("Location", createduri).build();
    }

    @DELETE
    @Path("{id}")
    public void remove(@PathParam("id") Integer id) {
        super.remove(super.find(id));
    }

    @GET
    @Path("{id}")
    @Produces({"application/xml", "application/json"})
    public Persona find(@PathParam("id") Integer id) {
        return super.find(id);
    }

    @GET
    @Override
    @Produces({"application/xml", "application/json"})
    public List<Persona> findAll() {
        return super.findAll();
    }

    @GET
    @Path("{from}/{to}")
    @Produces({"application/xml", "application/json"})
    public List<Persona> findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) {
        return super.findRange(new int[]{from, to});
    }

    @GET
    @Path("count")
    @Produces("text/plain")
    public String countREST() {
        return String.valueOf(super.count());
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
    /* Creacion de nuevos metodos 
     * Alexander Romero
     * Daniel Vasquez
     */
    /** 
     * @descripcion: metodo que devuelve todos los calendarios
     *               de un usuario
     */
    @GET
    @Path("{id}/calendarios")
    @Produces({"application/xml", "application/json"})
    public Collection<Calendario> findByPersonaCalender(@PathParam("id") Integer idPersona){
        return super.find(idPersona).getCalendarioCollection();
    }
    /**
     * @param id
     * @return 
     * @descripcion: obtenemos todos los caleandarios publicos de una persona
     *               
     */
    @GET
    @Path("{id}/calendario/publicos")
    @Produces({"application/xml", "application/json"})
    public Collection<Calendario> findByCalendariosPublicosPersona(@PathParam("id") Integer id){
        boolean publico=true;
        Collection<Calendario> calendariosPublicos=null;
             
        javax.persistence.Query q = getEntityManager().createNamedQuery("Calendario.findByCalendarPublicoPersona");
        q.setParameter("publico",publico);
        q.setParameter("idpersona",new Persona(id));
        calendariosPublicos=q.getResultList();
        return calendariosPublicos;
    }
    
    /**
     * @param id
     * @return 
     * @descripcion: obtenemos todos los caleandarios privados de una persona
     *               
     */
    @GET
    @Path("{id}/calendario/privados")
    @Produces({"application/xml", "application/json"})
    public Collection<Calendario> findByCalendarioPrivados(@PathParam("id") Integer id){
        boolean publico=false;
        Collection<Calendario> calendariosPrivados=null;
             
        javax.persistence.Query q = getEntityManager().createNamedQuery("Calendario.findByCalendarPublicoPersona");
        q.setParameter("publico",publico);
        q.setParameter("idpersona",new Persona(id));
        calendariosPrivados=q.getResultList();
        return calendariosPrivados;
    }
    
    /**
     * @descripcion: metodo que devuelve todas las citas de un usuario
     *               filtrando por fecha y/o por calendario o limita
     *               la cantidad de informacion por numero de cita
     * @param id
     * @param fromDate
     * @param toDate
     * @param idCalendar
     * @param nCitas
     * @return 
     */
    @GET
    @Path("{id}/citas")
    @Produces({"application/xml", "application/json"})
    public Collection<Cita> findByCitaPersona(@PathParam("id")      Integer id, 
                                              @QueryParam("from")   @DefaultValue("-1") String fromDate,
                                              @QueryParam("to")     @DefaultValue("-1") String toDate,
                                              @QueryParam("idCalendar") @DefaultValue("-1") String idCalendar, 
                                              @QueryParam("numCitas")   @DefaultValue("-1") String nCitas){
        //obtenemos todos los calendarios de la persona
        Collection<Calendario> colCalendarios = super.find(id).getCalendarioCollection();
        Collection<Cita> colCitas             = new ArrayList<Cita>();
        //obtenemos el id del calendario
        int idCalendario    = Integer.valueOf(idCalendar);
        int numCitas        = Integer.valueOf(nCitas);
        int cont;
        //recorremos los calendarios del usuario
        Iterator<Calendario> itCalendarios = colCalendarios.iterator();
        while( itCalendarios.hasNext()){
            Calendario calendarioVo = itCalendarios.next();
            if(idCalendario==-1){
                colCitas.addAll(calendarioVo.getCitaCollection());
            }
            else if(idCalendario==calendarioVo.getIdcalendario()){
                colCitas.addAll(calendarioVo.getCitaCollection());
                break;
            }
        }
        // verificamos si podemos enviar el listado de citas hasta ahora y 
        // terminar el proceso
        if(fromDate.equals("-1")||toDate.equals("-1")){
            if(numCitas==-1){
                return colCitas;
            }
            else{
                Iterator<Cita> itCitas         = colCitas.iterator();
                Collection<Cita> colNumCitas   = new ArrayList<Cita>();
                cont=0;
                while (itCitas.hasNext() && cont<numCitas){
                    Cita citaVo=itCitas.next();
                    colNumCitas.add(citaVo);
                    cont+=1;
                }
                return colNumCitas;
            }
        }
        // buscamos las citas que corresponden al rango especificado
        Iterator<Cita> itCitas         = colCitas.iterator();
        Collection<Cita> colNumCitas   = new ArrayList<Cita>();        
        cont=0;
        while(itCitas.hasNext()){
           try{ 
                Cita citaVo=itCitas.next();
                DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
                Date from = df.parse(fromDate);
                Date to = df.parse(toDate); 
                if (citaVo.getFechafin().after(from) && 
                    citaVo.getFechainicio().before(to)) {
                    colNumCitas.add(citaVo);
                }
                if(cont>numCitas && numCitas!=-1) {return colNumCitas;}
                cont+=1;
           }
           catch(ParseException e){
               System.out.println(e.getMessage());
           }
        } 
        return colNumCitas;
    } 
    
    /**
     *  @descripcion:obtenemos todas las citas publicas de todos calendarios publicos
     *              pudiendo filtrarlo por fecha y/o por calendario o limitar la 
     *              cantidad de informacion obtenidad por el numero de citas
     * @param id
     * @param fromDate
     * @param toDate
     * @param idCalendar
     * @param nCitas
     * @return 
     */
    @GET
    @Path("{id}/calendario/publicos/citas")
    @Produces({"application/xml", "application/json"})
    public Collection<Cita> findCitaPublicaPersona(@PathParam("id")      Integer id, 
                                              @QueryParam("from")   @DefaultValue("-1") String fromDate,
                                              @QueryParam("to")     @DefaultValue("-1") String toDate,
                                              @QueryParam("idCalendar") @DefaultValue("-1") String idCalendar, 
                                              @QueryParam("numCitas")   @DefaultValue("-1") String nCitas){
        //obtenemos todos los calendarios de la persona
        Collection<Calendario> colCalendarios = super.find(id).getCalendarioCollection();
        Collection<Cita> colCitas             = new ArrayList<Cita>();
        //obtenemos el id del calendario
        int idCalendario    = Integer.valueOf(idCalendar);
        int numCitas        = Integer.valueOf(nCitas);
        int cont;
        //recorremos los calendarios del usuario
        Iterator<Calendario> itCalendarios = colCalendarios.iterator();
        while( itCalendarios.hasNext()){
            Calendario calendarioVo = itCalendarios.next();
            if(idCalendario==-1 && calendarioVo.getPublico()){
                colCitas.addAll(calendarioVo.getCitaCollection());
            }
            else if(idCalendario==calendarioVo.getIdcalendario() &&
                    calendarioVo.getPublico()){
                colCitas.addAll(calendarioVo.getCitaCollection());
                break;
            }
        }
        // verificamos si podemos enviar el listado de citas hasta ahora y 
        // terminar el proceso
        if(fromDate.equals("-1")||toDate.equals("-1")){
            if(numCitas==-1){
                return colCitas;
            }
            else{
                Iterator<Cita> itCitas         = colCitas.iterator();
                Collection<Cita> colNumCitas   = new ArrayList<Cita>();
                cont=0;
                while (itCitas.hasNext() && cont<numCitas){
                    Cita citaVo=itCitas.next();
                    colNumCitas.add(citaVo);
                    cont+=1;
                }
                return colNumCitas;
            }
        }
        // buscamos las citas que corresponden al rango especificado
        Iterator<Cita> itCitas         = colCitas.iterator();
        Collection<Cita> colNumCitas   = new ArrayList<Cita>();        
        cont=0;
        while(itCitas.hasNext()){
           try{ 
                Cita citaVo=itCitas.next();
                DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
                Date from = df.parse(fromDate);
                Date to = df.parse(toDate); 
                if (citaVo.getFechafin().after(from) && 
                    citaVo.getFechainicio().before(to)) {
                    colNumCitas.add(citaVo);
                }
                if(cont>numCitas && numCitas!=-1) {return colNumCitas;}
                cont+=1;
           }
           catch(ParseException e){
               System.out.println(e.getMessage());
           }
        } 
        return colNumCitas;
    }
  }
